//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.ee9.nested;

import jakarta.servlet.AsyncContext;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Attributes;

import java.util.Set;

/**
 * An implementation of Attributes that supports the standard SSL and async attributes.
 */
public class ServletAttributes extends Attributes.Synthetic {
    private static final Set<String> ATTRIBUTES =
            Set.of(
                    Request.SSL_CIPHER_SUITE,
                    Request.SSL_KEY_SIZE,
                    Request.SSL_SESSION_ID,
                    Request.PEER_CERTIFICATES,
                    AsyncContext.ASYNC_REQUEST_URI,
                    AsyncContext.ASYNC_CONTEXT_PATH,
                    AsyncContext.ASYNC_SERVLET_PATH,
                    AsyncContext.ASYNC_PATH_INFO,
                    AsyncContext.ASYNC_QUERY_STRING,
                    AsyncContext.ASYNC_MAPPING
            );
    private Async _async;

    ServletAttributes(Attributes attributes) {
        super(attributes);
    }

    @Override
    protected Object getSyntheticAttribute(String name) {
        return switch (name) {
            case Request.SSL_CIPHER_SUITE ->
                    getWrapped().getAttribute(EndPoint.SslSessionData.ATTRIBUTE) instanceof EndPoint.SslSessionData sslSessionData ? sslSessionData.cipherSuite() : null;
            case Request.SSL_KEY_SIZE ->
                    getWrapped().getAttribute(EndPoint.SslSessionData.ATTRIBUTE) instanceof EndPoint.SslSessionData sslSessionData ? sslSessionData.keySize() : null;
            case Request.SSL_SESSION_ID ->
                    getWrapped().getAttribute(EndPoint.SslSessionData.ATTRIBUTE) instanceof EndPoint.SslSessionData sslSessionData ? sslSessionData.sslSessionId() : null;
            case Request.PEER_CERTIFICATES ->
                    getWrapped().getAttribute(EndPoint.SslSessionData.ATTRIBUTE) instanceof EndPoint.SslSessionData sslSessionData ? sslSessionData.peerCertificates() : null;
            case AsyncContext.ASYNC_REQUEST_URI -> _async == null ? null : _async.requestURI;
            case AsyncContext.ASYNC_CONTEXT_PATH -> _async == null ? null : _async.contextPath;
            case AsyncContext.ASYNC_SERVLET_PATH ->
                    _async == null ? null : _async.mapping == null ? null : _async.mapping.getServletPath();
            case AsyncContext.ASYNC_PATH_INFO ->
                    _async == null ? null : _async.mapping == null ? _async.pathInContext : _async.mapping.getPathInfo();
            case AsyncContext.ASYNC_QUERY_STRING -> _async == null ? null : _async.queryString;
            case AsyncContext.ASYNC_MAPPING -> _async == null ? null : _async.mapping;
            default -> null;
        };
    }

    @Override
    protected Set<String> getSyntheticNameSet() {
        return ATTRIBUTES;
    }

    public void setAsyncAttributes(String requestURI, String contextPath, String pathInContext, ServletPathMapping servletPathMapping, String queryString) {
        _async = new Async(requestURI, contextPath, pathInContext, servletPathMapping, queryString);
    }

    private record Async(
            String requestURI,
            String contextPath,
            String pathInContext,
            ServletPathMapping mapping,
            String queryString) {
    }
}
